package com.wutong.resonance.model.tool;

import com.wutong.resonance.model.plugin.Plugin;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;

/**
 * 插件队列，用于存放待执行的插件。
 * <p>
 * 插件执行顺序和添加顺序一致，采用先进先出(FIFO)原则。
 * @author wutong
 */
public class PluginQueue implements List<Plugin> {

    private final List<Plugin> plugins = new ArrayList<>();

    /**
     * 对 {@code Iterable} 的每个元素执行给定的操作，直到所有元素都已处理完毕或操作抛出异常。
     * 如果指定了迭代顺序，则按照迭代顺序执行操作。操作抛出的异常会传递给调用者。
     * <p>
     * 如果操作执行副作用，修改了元素的底层源，则此方法的行为未指定，除非重写类已指定并发修改策略。
     *
     * @param action 对每个元素执行的操作
     * @throws NullPointerException 如果指定的操作为 null
     * @implSpec <p>默认实现的行为如下：
     * <pre>{@code
     *     for (T t : this)
     *         action.accept(t);
     * }</pre>
     * @since 1.8
     */
    @Override
    public void forEach(Consumer<? super Plugin> action) {
        plugins.forEach(action);
    }

    /**
     * 返回一个包含此集合中所有元素的数组，使用提供的 {@code generator} 函数来分配返回的数组。
     *
     * <p>如果此集合保证其迭代器按什么顺序返回元素，则此方法必须按相同的顺序返回元素。
     *
     * @param generator 一个函数，它生成一个具有所需类型和提供长度的新数组
     * @param <T>       数组的组件类型
     * @return 一个包含此集合中所有元素的数组
     * @throws ArrayStoreException  如果此集合中任何元素的运行时类型不可分配给生成的数组的
     *                              {@linkplain Class#getComponentType 运行时组件类型}
     * @throws NullPointerException 如果 generator 函数为 null
     * @apiNote 此方法充当基于数组的 API 和基于集合的 API 之间的桥梁。 它允许创建特定运行时类型的数组。
     * 使用 {@link #toArray()} 创建运行时类型为 {@code Object[]} 的数组，或使用 {@link #toArray(Object[]) toArray(T[])}
     * 重用现有数组。
     *
     * <p>假设 {@code x} 是一个已知仅包含字符串的集合。 以下代码可用于将集合转储到新分配的 {@code String} 数组中：
     *
     * <pre>
     *     String[] y = x.toArray(String[]::new);</pre>
     * @implSpec 默认实现使用零调用 generator 函数，然后将生成的数组传递给 {@link #toArray(Object[]) toArray(T[])}。
     * @since 11
     */
    @Override
    public <T> T[] toArray(IntFunction<T[]> generator) {
        return plugins.toArray(generator);
    }

    /**
     * 删除此集合中所有满足给定谓词的元素。 迭代期间或谓词抛出的错误或运行时异常会传递给调用者。
     *
     * @param filter 一个谓词，它为要删除的元素返回 {@code true}
     * @return {@code true} 如果删除了任何元素
     * @throws NullPointerException          如果指定的 filter 为 null
     * @throws UnsupportedOperationException 如果无法从此集合中删除元素。 如果无法删除匹配元素，或者通常不支持删除，则实现可能会抛出此异常。
     * @implSpec 默认实现使用其 {@link #iterator} 遍历集合的所有元素。 使用 {@link Iterator#remove()} 删除每个匹配的元素。
     * 如果集合的迭代器不支持删除，则会在第一个匹配的元素上抛出 {@code UnsupportedOperationException}。
     * @since 1.8
     */
    @Override
    public boolean removeIf(Predicate<? super Plugin> filter) {
        return plugins.removeIf(filter);
    }

    /**
     * 返回一个以这个集合作为其源的顺序 {@code Stream}。
     *
     * <p>当 {@link #spliterator()} 方法无法返回一个 {@code IMMUTABLE}、{@code CONCURRENT} 或 <em>late-binding</em> 的 spliterator 时，应该重写此方法。（有关详细信息，请参阅 {@link #spliterator()}。）
     *
     * @return 一个关于此集合中元素的顺序 {@code Stream}
     * @implSpec 默认实现从集合的 {@code Spliterator} 创建一个顺序 {@code Stream}。
     * @since 1.8
     */
    @Override
    public Stream<Plugin> stream() {
        return plugins.stream();
    }

    /**
     * 返回一个以这个集合作为其源的可能并行的 {@code Stream}。 允许此方法返回一个顺序流。
     *
     * <p>当 {@link #spliterator()} 方法无法返回一个 {@code IMMUTABLE}、{@code CONCURRENT} 或 <em>late-binding</em> 的 spliterator 时，应该重写此方法。（有关详细信息，请参阅 {@link #spliterator()}。）
     *
     * @return 一个关于此集合中元素的可能并行的 {@code Stream}
     * @implSpec 默认实现从集合的 {@code Spliterator} 创建一个并行 {@code Stream}。
     * @since 1.8
     */
    @Override
    public Stream<Plugin> parallelStream() {
        return plugins.parallelStream();
    }

    /**
     * 返回此列表中元素的数量。如果此列表包含超过 {@code Integer.MAX_VALUE} 个元素，则返回 {@code Integer.MAX_VALUE}。
     *
     * @return 此列表中元素的数量
     */
    @Override
    public int size() {
        return plugins.size();
    }

    /**
     * 如果此列表不包含任何元素，则返回 {@code true}。
     *
     * @return {@code true} 如果此列表不包含任何元素
     */
    @Override
    public boolean isEmpty() {
        return plugins.isEmpty();
    }

    /**
     * 如果此列表包含指定的元素，则返回 {@code true}。 更正式地说，当且仅当此列表包含至少一个元素 {@code e}，使得
     * {@code Objects.equals(o, e)} 时，才返回 {@code true}。
     *
     * @param o 要测试其在此列表中是否存在的元素
     * @return {@code true} 如果此列表包含指定的元素
     * @throws ClassCastException   如果指定元素的类型与此列表不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException 如果指定的元素为 null，并且此列表不允许 null 元素 (<a href="Collection.html#optional-restrictions">可选</a>)
     */
    @Override
    public boolean contains(Object o) {
        return plugins.contains(o);
    }

    /**
     * 返回以适当顺序迭代此列表中元素的迭代器。
     *
     * @return 以适当顺序迭代此列表中元素的迭代器
     */
    @Override
    public Iterator<Plugin> iterator() {
        return plugins.iterator();
    }

    /**
     * 返回一个包含此列表中所有元素的数组，这些元素以正确的顺序（从第一个元素到最后一个元素）。
     *
     * <p>返回的数组将是“安全的”，因为此列表不会保留对其的引用。 （换句话说，即使此列表由数组支持，此方法也必须分配一个新数组）。
     * 因此，调用者可以自由地修改返回的数组。
     *
     * <p>此方法充当基于数组的 API 和基于集合的 API 之间的桥梁。
     *
     * @return 一个包含此列表中所有元素的数组，这些元素以正确的顺序排列
     * @see Arrays#asList(Object[])
     */
    @Override
    public Object[] toArray() {
        return plugins.toArray();
    }

    /**
     * 返回一个包含此列表中所有元素的数组，这些元素以正确的顺序（从第一个元素到最后一个元素）； 返回的数组的运行时类型是指定数组的运行时类型。
     * 如果列表适合指定的数组，则将其存储在该数组中。 否则，将分配一个具有指定数组的运行时类型和此列表大小的新数组。
     *
     * <p>如果列表适合具有剩余空间的指定数组（即，数组的元素多于列表），则数组中紧跟在列表末尾之后的元素设置为 {@code null}。
     * （仅当调用者知道该列表不包含任何 null 元素时，这对于确定列表的长度才有用。）
     *
     * <p>与 {@link #toArray()} 方法一样，此方法充当基于数组的 API 和基于集合的 API 之间的桥梁。 此外，此方法允许精确控制输出数组的运行时类型，
     * 并且在某些情况下，可用于节省分配成本。
     *
     * <p>假设 {@code x} 是一个已知仅包含字符串的列表。 以下代码可用于将列表转储到新分配的 {@code String} 数组中：
     *
     * <pre>{@code
     *     String[] y = x.toArray(new String[0]);
     * }</pre>
     *
     * 请注意，{@code toArray(new Object[0])} 在功能上与 {@code toArray()} 相同。
     *
     * @param a 用于存储此列表元素的数组，如果它足够大； 否则，将为此目的分配一个具有相同运行时类型的新数组。
     * @param <T> 返回的数组的组件类型
     * @return 一个包含此列表元素的数组
     * @throws ArrayStoreException  如果指定数组的运行时类型不是此列表中每个元素的运行时类型的超类型
     * @throws NullPointerException 如果指定的数组为 null
     */
    @Override
    public <T> T[] toArray(T[] a) {
        return plugins.toArray(a);
    }

    /**
     * 将指定的元素追加到此列表的末尾（可选操作）。
     *
     * <p>支持此操作的列表可能会限制可以添加到此列表中的元素。 特别是，某些列表将拒绝添加 null 元素，而另一些列表将对可以添加的元素的类型施加限制。
     * 列表类应在其文档中清楚地说明对可以添加的元素的任何限制。
     *
     * @param plugin 要追加到此列表的元素
     * @return {@code true} （如 {@link Collection#add} 中指定）
     * @throws UnsupportedOperationException 如果此列表不支持 {@code add} 操作
     * @throws ClassCastException            如果指定元素的类阻止将其添加到此列表
     * @throws NullPointerException          如果指定的元素为 null，并且此列表不允许 null 元素
     * @throws IllegalArgumentException      如果此元素的某些属性阻止将其添加到此列表
     */
    @Override
    public boolean add(Plugin plugin) {
        plugin.init();
        return plugins.add(plugin);
    }

    /**
     * 从此列表中删除指定元素的第一个匹配项（如果存在）（可选操作）。 如果此列表不包含该元素，则它不会更改。 更正式地说，删除具有最低索引 {@code i} 的元素
     * {@code i}，使得 {@code Objects.equals(o, get(i))}（如果存在此类元素）。 如果此列表包含指定的元素（或者，如果此列表因调用而更改），则返回 {@code true}。
     *
     * @param o 要从此列表中删除的元素（如果存在）
     * @return {@code true} 如果此列表包含指定的元素
     * @throws ClassCastException            如果指定元素的类型与此列表不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException          如果指定的元素为 null，并且此列表不允许 null 元素 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws UnsupportedOperationException 如果此列表不支持 {@code remove} 操作
     */
    @Override
    public boolean remove(Object o) {
        if (o instanceof Plugin) {
            ((Plugin) o).unload();
        }
        return plugins.remove(o);
    }

    /**
     * 如果此列表包含指定集合的所有元素，则返回 {@code true}。
     *
     * @param c 要检查其是否包含在此列表中的集合
     * @return {@code true} 如果此列表包含指定集合的所有元素
     * @throws ClassCastException   如果指定集合中一个或多个元素的类型与此列表不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException 如果指定的集合包含一个或多个 null 元素，并且此列表不允许 null 元素
     *                              (<a href="Collection.html#optional-restrictions">可选</a>)，或者如果指定的集合为 null
     * @see #contains(Object)
     */
    @Override
    public boolean containsAll(Collection<?> c) {
        return new HashSet<>(plugins).containsAll(c);
    }

    /**
     * 将指定集合中的所有元素按指定集合的迭代器返回的顺序追加到此列表的末尾（可选操作）。 如果在操作进行时修改了指定的集合，则此操作的行为未定义。
     * （请注意，如果指定的集合是此列表且非空，则会发生这种情况。）
     *
     * @param c 包含要添加到此列表的元素的集合
     * @return {@code true} 如果此列表因调用而更改
     * @throws UnsupportedOperationException 如果此列表不支持 {@code addAll} 操作
     * @throws ClassCastException            如果指定集合的元素的类阻止将其添加到此列表
     * @throws NullPointerException          如果指定的集合包含一个或多个 null 元素，并且此列表不允许 null 元素，或者如果指定的集合为 null
     * @throws IllegalArgumentException      如果指定集合的元素的某些属性阻止将其添加到此列表
     * @see List#add(Object)
     */
    @Override
    public boolean addAll(Collection<? extends Plugin> c) {
        for (Plugin plugin : c) {
            plugin.init();
        }
        return plugins.addAll(c);
    }

    /**
     * 将指定集合中的所有元素插入到此列表中的指定位置（可选操作）。 将当前位于该位置的元素（如果有）和任何后续元素向右移动（增加其索引）。
     * 新元素将按指定集合的迭代器返回的顺序显示在此列表中。 如果在操作进行时修改了指定的集合，则此操作的行为未定义。
     * （请注意，如果指定的集合是此列表且非空，则会发生这种情况。）
     *
     * @param index 要在其中插入指定集合的第一个元素的索引
     * @param c     包含要添加到此列表的元素的集合
     * @return {@code true} 如果此列表因调用而更改
     * @throws UnsupportedOperationException 如果此列表不支持 {@code addAll} 操作
     * @throws ClassCastException            如果指定集合的元素的类阻止将其添加到此列表
     * @throws NullPointerException          如果指定的集合包含一个或多个 null 元素，并且此列表不允许 null 元素，或者如果指定的集合为 null
     * @throws IllegalArgumentException      如果指定集合的元素的某些属性阻止将其添加到此列表
     * @throws IndexOutOfBoundsException     如果索引超出范围 ({@code index < 0 || index > size()})
     */
    @Override
    public boolean addAll(int index, Collection<? extends Plugin> c) {
        for (Plugin plugin : c) {
            plugin.init();
        }
        return plugins.addAll(index, c);
    }

    /**
     * 从此列表中删除指定集合中包含的所有元素（可选操作）。
     *
     * @param c 包含要从此列表中删除的元素的集合
     * @return {@code true} 如果此列表因调用而更改
     * @throws UnsupportedOperationException 如果此列表不支持 {@code removeAll} 操作
     * @throws ClassCastException            如果此列表的元素的类与指定的集合不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException          如果此列表包含一个 null 元素，并且指定的集合不允许 null 元素
     *                                       (<a href="Collection.html#optional-restrictions">可选</a>)，或者如果指定的集合为 null
     * @see #remove(Object)
     * @see #contains(Object)
     */
    @Override
    public boolean removeAll(Collection<?> c) {
        for (Object o : c) {
            if (o instanceof Plugin) {
                ((Plugin) o).unload();
            }
        }
        return plugins.removeAll(c);
    }

    /**
     * 仅保留此列表中指定集合中包含的元素（可选操作）。 换句话说，从此列表中删除所有未包含在指定集合中的元素。
     *
     * @param c 包含要保留在此列表中的元素的集合
     * @return {@code true} 如果此列表因调用而更改
     * @throws UnsupportedOperationException 如果此列表不支持 {@code retainAll} 操作
     * @throws ClassCastException            如果此列表的元素的类与指定的集合不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException          如果此列表包含一个 null 元素，并且指定的集合不允许 null 元素
     *                                       (<a href="Collection.html#optional-restrictions">可选</a>)，或者如果指定的集合为 null
     * @see #remove(Object)
     * @see #contains(Object)
     */
    @Override
    public boolean retainAll(Collection<?> c) {
        for (Plugin o : plugins) {
            if (!c.contains(o)) {
                o.unload();
            }
        }
        return plugins.retainAll(c);
    }

    /**
     * 使用将运算符应用于该元素的结果替换此列表的每个元素。 运算符抛出的错误或运行时异常会传递给调用者。
     *
     * @param operator 要应用于每个元素的运算符
     * @throws UnsupportedOperationException 如果此列表是不可修改的。 如果无法替换元素，或者通常不支持修改，则实现可能会抛出此异常
     * @throws NullPointerException          如果指定的运算符为 null，或者运算符结果为 null 值，并且此列表不允许 null 元素
     *                                       (<a href="Collection.html#optional-restrictions">可选</a>)
     * @implSpec 默认实现等效于此 {@code list}：
     * <pre>{@code
     *     final ListIterator<E> li = list.listIterator();
     *     while (li.hasNext()) {
     *         li.set(operator.apply(li.next()));
     *     }
     * }</pre>
     *
     * 如果列表的列表迭代器不支持 {@code set} 操作，则在替换第一个元素时会抛出 {@code UnsupportedOperationException}。
     * @since 1.8
     */
    @Override
    public void replaceAll(UnaryOperator<Plugin> operator) {
        plugins.replaceAll(operator);
    }

    /**
     * 根据指定的 {@link Comparator} 引发的顺序对此列表进行排序。 排序是<i>稳定的</i>：此方法不得对相等元素进行重新排序。
     *
     * <p>此列表中的所有元素必须使用指定的比较器是<i>相互可比较的</i>（也就是说，对于列表中的任何元素 {@code e1} 和 {@code e2}，{@code c.compare(e1, e2)}
     * 不得抛出 {@code ClassCastException}）。
     *
     * <p>如果指定的比较器为 {@code null}，则此列表中的所有元素必须实现 {@link Comparable} 接口，并且应使用元素的 {@linkplain Comparable 自然排序}。
     *
     * <p>此列表必须是可修改的，但不必是可调整大小的。
     *
     * @param c 用于比较列表元素的 {@code Comparator}。 {@code null} 值表示应使用元素的 {@linkplain Comparable 自然排序}
     * @throws ClassCastException            如果列表包含使用指定的比较器不是<i>相互可比较的</i>元素
     * @throws UnsupportedOperationException 如果列表的列表迭代器不支持 {@code set} 操作
     * @throws IllegalArgumentException      (<a href="Collection.html#optional-restrictions">可选</a>) 如果发现比较器违反了 {@link Comparator} 契约
     * @implSpec 默认实现获取一个包含此列表中所有元素的数组，对该数组进行排序，并迭代此列表，从数组中的相应位置重置每个元素。 （这避免了尝试就地对链接列表进行排序时会产生的 n<sup>2</sup> log(n) 性能。）
     * @implNote 此实现是一种稳定的、自适应的、迭代的归并排序，当输入数组部分排序时，需要的比较次数远少于 n lg(n)，同时在输入数组随机排序时提供传统归并排序的性能。
     * 如果输入数组几乎已排序，则该实现需要大约 n 次比较。 临时存储要求从几乎已排序的输入数组的小常量到随机排序的输入数组的 n/2 对象引用不等。
     *
     * <p>该实现充分利用其输入数组中的升序和降序，并且可以利用同一输入数组不同部分中的升序和降序。 它非常适合合并两个或多个排序的数组：只需连接数组并对生成的数组进行排序。
     *
     * <p>该实现改编自 Tim Peters 的 Python 列表排序 (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt"> TimSort</a>)。
     * 它使用了 Peter McIlroy 的“乐观排序和信息理论复杂性”中的技术，载于第四届年度 ACM-SIAM 离散算法研讨会论文集，第 467-474 页，1993 年 1 月。
     * @since 1.8
     */
    @Override
    public void sort(Comparator<? super Plugin> c) {
        plugins.sort(c);
    }

    /**
     * 从此列表中删除所有元素（可选操作）。 调用返回后，列表将为空。
     *
     * @throws UnsupportedOperationException 如果此列表不支持 {@code clear} 操作
     */
    @Override
    public void clear() {
        for (Plugin plugin : plugins) {
            plugin.unload();
        }
        plugins.clear();
    }

    /**
     * 返回此列表中指定位置的元素。
     *
     * @param index 要返回的元素的索引
     * @return 此列表中指定位置的元素
     * @throws IndexOutOfBoundsException 如果索引超出范围 ({@code index < 0 || index >= size()})
     */
    @Override
    public Plugin get(int index) {
        return plugins.get(index);
    }

    /**
     * 使用指定的元素替换此列表中指定位置的元素（可选操作）。
     *
     * @param index   要替换的元素的索引
     * @param element 要存储在指定位置的元素
     * @return 先前位于指定位置的元素
     * @throws UnsupportedOperationException 如果此列表不支持 {@code set} 操作
     * @throws ClassCastException            如果指定元素的类阻止将其添加到此列表
     * @throws NullPointerException          如果指定的元素为 null，并且此列表不允许 null 元素
     * @throws IllegalArgumentException      如果指定元素的某些属性阻止将其添加到此列表
     * @throws IndexOutOfBoundsException     如果索引超出范围 ({@code index < 0 || index >= size()})
     */
    @Override
    public Plugin set(int index, Plugin element) {
        plugins.get(index).unload();
        element.init();
        return plugins.set(index, element);
    }

    /**
     * 将指定的元素插入到此列表中的指定位置（可选操作）。 将当前位于该位置的元素（如果有）和任何后续元素向右移动（将其索引加 1）。
     *
     * @param index   要在其中插入指定元素的索引
     * @param element 要插入的元素
     * @throws UnsupportedOperationException 如果此列表不支持 {@code add} 操作
     * @throws ClassCastException            如果指定元素的类阻止将其添加到此列表
     * @throws NullPointerException          如果指定的元素为 null，并且此列表不允许 null 元素
     * @throws IllegalArgumentException      如果指定元素的某些属性阻止将其添加到此列表
     * @throws IndexOutOfBoundsException     如果索引超出范围 ({@code index < 0 || index > size()})
     */
    @Override
    public void add(int index, Plugin element) {
        element.init();
        plugins.add(index, element);
    }

    /**
     * 删除此列表中指定位置的元素（可选操作）。 将任何后续元素向左移动（将其索引减 1）。 返回从列表中删除的元素。
     *
     * @param index 要删除的元素的索引
     * @return 先前位于指定位置的元素
     * @throws UnsupportedOperationException 如果此列表不支持 {@code remove} 操作
     * @throws IndexOutOfBoundsException     如果索引超出范围 ({@code index < 0 || index >= size()})
     */
    @Override
    public Plugin remove(int index) {
        plugins.get(index).unload();
        return plugins.remove(index);
    }

    /**
     * 返回此列表中指定元素的第一个匹配项的索引，如果此列表不包含该元素，则返回 -1。 更正式地说，返回最低索引 {@code i}，使得 {@code Objects.equals(o, get(i))}，
     * 如果不存在此类索引，则返回 -1。
     *
     * @param o 要搜索的元素
     * @return 此列表中指定元素的第一个匹配项的索引，如果此列表不包含该元素，则返回 -1
     * @throws ClassCastException   如果指定元素的类型与此列表不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException 如果指定的元素为 null，并且此列表不允许 null 元素 (<a href="Collection.html#optional-restrictions">可选</a>)
     */
    @Override
    public int indexOf(Object o) {
        return plugins.indexOf(o);
    }

    /**
     * 返回此列表中指定元素的最后一个匹配项的索引，如果此列表不包含该元素，则返回 -1。 更正式地说，返回最高索引 {@code i}，使得 {@code Objects.equals(o, get(i))}，
     * 如果不存在此类索引，则返回 -1。
     *
     * @param o 要搜索的元素
     * @return 此列表中指定元素的最后一个匹配项的索引，如果此列表不包含该元素，则返回 -1
     * @throws ClassCastException   如果指定元素的类型与此列表不兼容 (<a href="Collection.html#optional-restrictions">可选</a>)
     * @throws NullPointerException 如果指定的元素为 null，并且此列表不允许 null 元素 (<a href="Collection.html#optional-restrictions">可选</a>)
     */
    @Override
    public int lastIndexOf(Object o) {
        return plugins.lastIndexOf(o);
    }

    /**
     * 返回一个以适当顺序迭代此列表中元素的列表迭代器。
     *
     * @return 一个以适当顺序迭代此列表中元素的列表迭代器
     */
    @Override
    public ListIterator<Plugin> listIterator() {
        return plugins.listIterator();
    }

    /**
     * 返回一个以适当顺序迭代此列表中元素的列表迭代器，从列表中的指定位置开始。 指定的索引指示通过对 {@link ListIterator#next next} 的初始调用返回的第一个元素。
     * 对 {@link ListIterator#previous previous} 的初始调用将返回具有指定索引减 1 的元素。
     *
     * @param index 要从列表迭代器返回的第一个元素的索引（通过调用 {@link ListIterator#next next}）
     * @return 一个以适当顺序迭代此列表中元素的列表迭代器，从列表中的指定位置开始
     * @throws IndexOutOfBoundsException 如果索引超出范围 ({@code index < 0 || index > size()})
     */
    @Override
    public ListIterator<Plugin> listIterator(int index) {
        return plugins.listIterator(index);
    }

    /**
     * 返回此列表在指定的 {@code fromIndex}（包括）和 {@code toIndex}（不包括）之间的部分的视图。 （如果 {@code fromIndex} 和 {@code toIndex} 相等，则返回的列表为空。）
     * 返回的列表由此列表支持，因此返回的列表中的非结构性更改会反映在此列表中，反之亦然。 返回的列表支持此列表支持的所有可选列表操作。
     *
     * <p>此方法消除了对显式范围操作（通常存在于数组中）的需求。 通过传递 subList 视图而不是整个列表，可以使用任何期望列表的操作作为范围操作。
     * 例如，以下习惯用法从列表中删除一系列元素：
     * <pre>{@code
     *      list.subList(from, to).clear();
     * }</pre>
     * 可以为 {@code indexOf} 和 {@code lastIndexOf} 构建类似的习惯用法，并且可以将 {@code Collections} 类中的所有算法应用于 subList。
     *
     * <p>如果后备列表（即此列表）以除通过返回的列表之外的任何方式<i>结构性地修改</i>，则由此方法返回的列表的语义将变得未定义。
     * （结构性修改是指更改此列表的大小，或者以某种方式扰乱它，从而导致正在进行的迭代可能会产生不正确的结果。）
     *
     * @param fromIndex subList 的低端点（包括）
     * @param toIndex   subList 的高端点（不包括）
     * @return 此列表中指定范围的视图
     * @throws IndexOutOfBoundsException 对于非法端点索引值
     *                                   ({@code fromIndex < 0 || toIndex > size || fromIndex > toIndex})
     */
    @Override
    public List<Plugin> subList(int fromIndex, int toIndex) {
        return plugins.subList(fromIndex, toIndex);
    }

    /**
     * 创建此列表中元素的 {@link Spliterator}。
     *
     * <p>{@code Spliterator} 报告 {@link Spliterator#SIZED} 和 {@link Spliterator#ORDERED}。 实现应记录附加特征值的报告。
     *
     * @return 此列表中元素的 {@code Spliterator}
     * @implSpec 默认实现创建一个
     * <em><a href="Spliterator.html#binding">late-binding</a></em>
     * spliterator，如下所示：
     * <ul>
     * <li>如果列表是 {@link RandomAccess} 的实例，则默认实现会创建一个 spliterator，该 spliterator 通过调用方法 {@link List#get} 来遍历元素。 如果此类调用导致或将导致 {@code IndexOutOfBoundsException}，
     * 则 spliterator 将会<i>快速失败</i>并抛出 {@code ConcurrentModificationException}。 如果列表也是 {@link AbstractList} 的实例，
     * 则 spliterator 将使用列表的 {@code AbstractList.modCount modCount} 字段来提供额外的<i>快速失败</i>行为。
     * <li>否则，默认实现会从列表的 {@code Iterator} 创建一个 spliterator。 spliterator 继承列表的迭代器的<i>快速失败</i>。
     * </ul>
     * @implNote 创建的 {@code Spliterator} 还会报告 {@link Spliterator#SUBSIZED}。
     * @since 1.8
     */
    @Override
    public Spliterator<Plugin> spliterator() {
        return plugins.spliterator();
    }

    /**
     * {@inheritDoc}
     *
     * @param plugin
     * @throws NullPointerException          {@inheritDoc}
     * @throws UnsupportedOperationException {@inheritDoc}
     * @implSpec 此接口中的实现调用 {@code add(0, e)}。
     * @since 21
     */
    @Override
    public void addFirst(Plugin plugin) {
        plugin.init();
        plugins.addFirst(plugin);
    }

    /**
     * {@inheritDoc}
     *
     * @param plugin
     * @throws NullPointerException          {@inheritDoc}
     * @throws UnsupportedOperationException {@inheritDoc}
     * @implSpec 此接口中的实现调用 {@code add(e)}。
     * @since 21
     */
    @Override
    public void addLast(Plugin plugin) {
        plugin.init();
        plugins.add(plugin);
    }

    /**
     * {@inheritDoc}
     *
     * @return
     * @throws NoSuchElementException {@inheritDoc}
     * @implSpec 如果此 List 不为空，则此接口中的实现返回调用 {@code get(0)} 的结果。 否则，它会抛出 {@code NoSuchElementException}。
     * @since 21
     */
    @Override
    public Plugin getFirst() {
        if (plugins.isEmpty()) {
            throw new NoSuchElementException("PluginQueue is empty.");
        }
        return plugins.getFirst();
    }

    /**
     * {@inheritDoc}
     *
     * @throws NoSuchElementException {@inheritDoc}
     * @implSpec 如果此 List 不为空，则此接口中的实现返回调用 {@code get(size() - 1)} 的结果。 否则，它会抛出 {@code NoSuchElementException}。
     * @since 21
     */
    @Override
    public Plugin getLast() {
        if (plugins.isEmpty()) {
            throw new NoSuchElementException("PluginQueue is empty.");
        }
        return plugins.getLast();
    }

    /**
     * {@inheritDoc}
     *
     * @throws NoSuchElementException        {@inheritDoc}
     * @throws UnsupportedOperationException {@inheritDoc}
     * @implSpec 如果此 List 不为空，则此接口中的实现返回调用 {@code remove(0)} 的结果。 否则，它会抛出 {@code NoSuchElementException}。
     * @since 21
     */
    @Override
    public Plugin removeFirst() {
        if (plugins.isEmpty()) {
            throw new NoSuchElementException("PluginQueue is empty.");
        }
        plugins.getFirst().unload();
        return plugins.removeFirst();
    }

    /**
     * {@inheritDoc}
     *
     * @throws NoSuchElementException        {@inheritDoc}
     * @throws UnsupportedOperationException {@inheritDoc}
     * @implSpec 如果此 List 不为空，则此接口中的实现返回调用 {@code remove(size() - 1)} 的结果。 否则，它会抛出 {@code NoSuchElementException}。
     * @since 21
     */
    @Override
    public Plugin removeLast() {
        if (plugins.isEmpty()) {
            throw new NoSuchElementException("PluginQueue is empty.");
        }
        plugins.getLast().unload();
        return plugins.removeLast();
    }

    /**
     * {@inheritDoc}
     *
     * @return 此集合的逆序视图，作为 {@code List}
     * @implSpec 此接口中的实现返回逆序 List 视图。 视图的 {@code reversed()} 方法返回对该 List 的引用。
     * 对视图的其他操作通过调用此 List 上的公共方法来实现。 未指定对视图的调用与对此 List 的调用之间的确切关系。 但是，
     * 顺序敏感操作通常委托给具有相反方向的相应方法。 例如，在视图上调用 {@code getFirst} 会导致对此 List 上的 {@code getLast} 的调用。
     * @since 21
     */
    @Override
    public List<Plugin> reversed() {
        return List.super.reversed();
    }
}